// Prototype
// Version 1.0.0

#include <p32xxxx.h>
#include <plib.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "HelmetSystemConfig.h"
#include "HelmetADC.h"
#include "HelmetTimers.h"
#include "HelmetLEDs.h"
#include "HelmetInputs.h"
#include "HelmetExternalInterrupts.h"
#include "HelmetUART.h"
#include "HelmetI2C.h"
#include "HelmetOutputs.h"
#include "AtomControl.h"

/**************************************************************************************
	Main
**************************************************************************************/
main() {
	
	/**************************************
		Configure LEDs
	**************************************/
	ConfigLEDs();
	
	/**************************************
		Turn On Heartbeat LED
	**************************************/
	SetHEARTBEAT();
	
	/**************************************
		Config System
	**************************************/
	ConfigSystem();
	
	/**************************************
		Configure Timer 1
	**************************************/
	ConfigTimer1();
    
    /**************************************
		Configure Atom
	**************************************/	
	ConfigAtom();
	
	/**************************************
		Configure GPS
	**************************************/	
    ConfigGPS();
    
    /**************************************
		Configure Fuel Gauge
	**************************************/
	ConfigFuelGauge();
    
    /**************************************
		Configure ADC
	**************************************/	
	ConfigADC();
	
	/**************************************
		Configure Inputs
	**************************************/
	ConfigInputs();
	
	/**************************************
		Configure Outputs
	**************************************/
	ConfigAllOutputs();
	
	/**************************************
		Configure External Interrupts
	**************************************/
	ConfigExternalInterrupts();
	
	/**************************************
		Enable interrupts
	**************************************/
    EnableInterrupts();
	
	/**************************************
		Startup Message
	**************************************/
	WriteAtom("====================================\r\n");
	
	/**************************************
		Start-up Atom for First Use
	**************************************/
	AtomStartUp();
	
	/**************************************
		Main Loop
	**************************************/
	float accel; // magnitude of g-force experienced
	char lastreadgps; // last GPS character read
	char msg[50]; // generic output message
	float hangtime; // actual hangtime float
	float avgtemp = 0.0; // average temperature
	float avgaccel = 0.0; // average acceleration
	float avgphoto = 0.0; // average photocell value
	unsigned int i=0; // for random waiting
	
	while( 1 ) {
		
		// Enter sleep mode
		if( EnterSleepMode ) {
			WriteAtom ("Sleep ENTER\r\n");
			// Sleep GPS and Accel
			GPSSleep();
			AccelSleep();
			// clean up GPS buffer
			ClearGPSBuffer();
			// Clean up stuff that might be on
			VibMotorOff();
			ButtonLEDsOff();
			ClearAllLEDs();
			SetHEARTBEAT();
			FansOff();
			VibMotorOff();
			AtomShutDown();
			ClearHEARTBEAT();
			Finished( EnterSleepMode );
			Sleeping = 1;
			// Finally, enter sleep mode
			PowerSaveSleep();
		}
		
		// Exit sleep mode
		if( ExitSleepMode ) {
			i=1000000; // wait a bit
			while( i>0 ) i--;
			WriteAtom("Sleep WAKE\r\n");
			// Enable GPS and Accel
			GPSRun();
			AccelRun();
			// Change GPS to Alive state initially
			GPSAlive = 3;
			AtomStartUp();
			Finished( ExitSleepMode );
		}
		
		// Remote button pad
		if( CheckRemoteButtonPad ) {
			char b = 0;
			b = GetRemoteButtonPressed();
			sprintf( msg, "Buttn %c\r\n",  b );
			WriteAtom( msg );
			Finished( CheckRemoteButtonPad );
		}
		
		if( CheckAttachedButtonPad ) {
			char b = 0;
			b = GetAttachedButtonPressed();
			if( b == prevButton ) {
				// do nothing
			} else {
				prevButton = b;
				sprintf( msg, "Buttn %c\r\n", b );
				WriteAtom( msg );
			}	
			Finished( CheckAttachedButtonPad );
		}
		
		// Read the GPS message
		if( ReadGPSMessage ) {
			if( ParseGPSMessage() ) {
				Finished( ReadGPSMessage );
			}
		}
		
		// Interpret the GPS message once read
		if( InterpretGPSMessage ) {
			OutputGPSMessage();
			Finished( InterpretGPSMessage );
		}
		
		// Query GPS for status
		if( GPSQuery ) {
			WriteGPS(">QST<\r");
			WriteGPS(">QTM<\r");
			WriteGPS(">QLN<\r");
			Finished( GPSQuery );
		}	
		
		// Report a gps failure
		if( ReportGPSFailure ) {
			WriteAtom( "Error GPS failure\r\n" );
			Finished( ReportGPSFailure );	
		}	
		
		// Interpret ADC sample data and report acceleration
		if( ConvertADC ) {			
			accel = ConvertADCData();
			sprintf( msg, "Accel %3.1f\r\n", accel );
			WriteAtom( msg );
			Finished( ConvertADC );
		}
		
		// Report Hang Time
		if( ReportHangTime ) {
			hangtime = GetHangTime(); 
			sprintf( msg, "HangT %.2f", hangtime ); 
			WriteAtom( msg );
			Finished( ReportHangTime );
		}
		
		// Report Averages
		if( ReportAverages ) {
			avgaccel = GetAverageAcceleration();
			avgtemp = GetAverageTemperature();
			avgphoto = GetAveragePhotocellLevel();
			sprintf( msg, "Avges %.1f %.1f %.0f\r\n", avgaccel, avgtemp, avgphoto );
			WriteAtom( msg );
			Finished( ReportAverages );
		}	
		
		// Check Fuel Gauge
		if( CheckFuelGauge >= FUEL_GAUGE_CHECK_INTERVAL ) {
			OutputFuelGaugeData(); // disabled while 2782 is dead
			Finished( CheckFuelGauge );
		}
		
		/*
		MainLoopIterationsPerSecond ++;
		if( ReportMLIPS ) {
			sprintf( msg, "MLIPS %.0f\r\n", (float)MainLoopIterationsPerSecond );
			WriteAtom( msg );
			MainLoopIterationsPerSecond = 0;
			Finished( ReportMLIPS );
		}
		*/	
		
	} // main loop
	
}

